package com.cskaoyan.javse.object._2tostring;

/**
 * @description: toString方法
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * toString方法
 * 1.方法的声明: public String toString()
 *      没有访问权限限制,也不需要参数,唯一需要注意的是该方法的返回值是String字符串
 *
 * 2.作用:
 *      a.返回该对象(调用toString方法的对象)的字符串表示。(该方法把对象 ---> 字符串)
 *      b.通常，toString 方法会返回一个“以文本方式表示”此对象的字符串。
 *      c.结果应是一个简明但易于读懂的信息表达式。
 *      d.建议所有子类都重写此方法。(java设计者自己都觉得Object类当中的默认实现不是一个最优解)
 *
 * 3.Object类当中的toString方法实现:
 *      return getClass().getName() + "@" + Integer.toHexString(hashCode());
 * 用当前对象调用getClass方法,获取该对象的运行时类对象,然后再调用getName方法,获取该类型的全限定类名
 * 后面跟一个"@"
 * hashCode()该方法返回当前对象的哈希值,注意Object类的默认实现是通过计算对象的地址,转换成一个十进制的数字
 *      也就是说,hashCode()方法得到的是一个十进制的该对象地址值
 * Integer.toHexString()再将十进制的地址值转换成十六进制的地址值字符串
 *
 * 以上,Object类中toString方法的默认实现是打印,对象的全限定类名+@+十六进制地址值
 *
 * 4.实际上,如果不做额外操作(不重写toString方法)的情况下,直接打印对象名,就会调用该类继承自Object类的toString方法,并且任何把对象和字符串进行操作的写法,都会自动toString方法
 *
 * 其实在多数时候，我们并不关心全限定类名和地址值，更多的时候我们希望能够看到对象中成员变量的取值，于是需要在子类中重写该方法，重写的原则是：打印成员变量的取值
 *      格式： 类名{成员变量1 = 值，成员变量2 = 值....}
 *
 * 以上方法重写，需要注意以下几个问题：
 *      1.toString方法就是为了完成打印成员变量取值的工作的，不要在里面写一些奇怪的代码，如果：赋值或者改变成员变量的数据类型等等。因为debug模式也会自动调用类的toString方法
 *      2.toString方法可以快速自动生成，仍然用alt+insert，一般情况下，没有特殊需求，直接自动生成即可
 *      3.如果类中有（自定义）引用数据类型成员变量，也需要重写成员变量类的toString方法（String的除外)
 *      4.为了避免空指针异常，隐含调用的toString方法能不写出来就不要写出来，不要画蛇添足
 *
 */
public class Demo {
    public static void main(String[] args) {
        /*Student s = new Student(1,18,100);
        //System.out.println(s);
        System.out.println(s.age);*/

        Student s = new Student(null, 1, 88, 99);
        System.out.println(s);

    }
}

class Student {

    Star s;
    int id;
    int age;
    double score;

    public Student() {
    }

    public Student(int id, int age, double score) {
        this.id = id;
        this.age = age;
        this.score = score;
    }

    public Student(Star s, int id, int age, double score) {
        this.s = s;
        this.id = id;
        this.age = age;
        this.score = score;
    }

    //重写toString()方法
    //重写的规则是打印成员变量的取值
    /*@Override
    public String toString() {
        //age = 100;
        return "Student{id = " + id + ", age = " + age + ", score = " + score + " }";
    }*/
    /*@Override
    public String toString() {
        return "Student{" +
                "Star{ " + "age = " + age + "}," +
                "id=" + id +
                ", age=" + age +
                ", score=" + score +
                '}';
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "s=" + s +
                ", id=" + id +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

class Star {
    int age;

    public Star() {
    }

    public Star(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Star{" +
                "age=" + age +
                '}';
    }
}